package cn.sixmillions.ps.controller;


import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileTypeUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.sixmillions.ps.common.base.R;
import cn.sixmillions.ps.config.MinioConfig;
import cn.sixmillions.ps.entity.MinioFileHis;
import cn.sixmillions.ps.service.IMinioFileHisService;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.errors.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDate;
import java.util.Date;

/**
 * 上传文件到MinIO
 *
 * @author six
 * @since 2023-01-31
 */
@RestController
@RequestMapping("/api/minio")
@RequiredArgsConstructor
@Slf4j
@CrossOrigin("*")
public class MinioController {

    final private MinioConfig minioConfig;
    final private MinioClient minioClient;
    final private IMinioFileHisService minioFileHisService;

    @PostMapping("/single-upload")
    public R upload(MultipartFile file) {
        //获取文件名
        String originalFilename = file.getOriginalFilename();
        //上传路径（例如：“2023/02/01”）
        String filePath = LocalDateTimeUtil.format(LocalDate.now(), "yyyy/MM/dd");
        //获取文件后缀名
        String suffixName = StringPool.EMPTY;
        if (StringUtils.isNotBlank(originalFilename) && originalFilename.contains(StringPool.DOT)) {
            suffixName = originalFilename.substring(originalFilename.lastIndexOf(StringPool.DOT));
        }
        //新文件名
        String newFileName = String.format("%s%s%s",
                DateUtil.format(new Date(), DatePattern.PURE_TIME_PATTERN),
                RandomUtil.randomString(4),
                suffixName);
        String fullPath = String.format("%s/%s", filePath, newFileName);
        String fileType;
        //上传文件（斜杠会认为是文件夹;文件名称相同会覆盖）
        try (InputStream ins = file.getInputStream()) {
            PutObjectArgs objectArgs = PutObjectArgs.builder()
                    .bucket(minioConfig.getBucketName())
                    .object(fullPath)
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build();
            minioClient.putObject(objectArgs);
            fileType = FileTypeUtil.getType(ins);
        } catch (IOException | ErrorResponseException | InsufficientDataException | InternalException |
                 InvalidKeyException | InvalidResponseException | NoSuchAlgorithmException | ServerException |
                 XmlParserException e) {
            log.error("上传文件到MinIO异常", e);
            throw new RuntimeException("上传文件到MinIO异常");
        }
        //异步保存上传记录
        MinioFileHis fileHis = MinioFileHis.builder()
                .bucketName(minioConfig.getBucketName())
                .filePath(filePath)
                .fileName(newFileName)
                .originName(originalFilename)
                .fileSize(NumberUtil.round((double) file.getSize() / 1024, 2).doubleValue())
                .fileType(fileType)
                .createdBy("sys")
                .lastModifiedBy("sys")
                .build();
        minioFileHisService.asyncSaveUploadHis(fileHis);
        return R.data(String.format(minioConfig.getBaseUrl(), fullPath));
    }

}

